This is an introduction to `gear` for the people who already have the RPM
packaging experience and know how to use git.

# Purpose of gear

Gear is a set of tools for maintenance and release management of RPM
packages based on a git repository. A gear-enabled git repository of a
software package combines:

* software development history
* modifications necessary to produce an RPM package
* rules to bind software releases to specific RPM-based distribution releases

Developers using Gear need to understand
* a format of the rules file describing transformation procedures that convert a
  given git changeset and branches to a number of source files for a RPM package
* utilities for building packages and working with source code (importing
  upstream sources and managing patches)

# RPM-specific stuff

RPM source packages are built using the following files:
* .spec file, which is roughly debian/* without debian/patches/*
* a number of source files/archives
* optionally patches containing local fixes to the upstream source code

Gear gives a way to automate generation of patches and source files off the git
repostiory.

# Working with upstream source code

A source code of a project is generally tracked in a separate branch that could
be synchronized with a corresponding upstream repository by traditional git
tools. When the upstream of the project does not use a VCS that allows direct
import into git, the source code can still be managed with archives and source
RPM packages.

## SRPMs

```sh
$ gear-srpmimport some-0.1.src.rpm
$ gear-srpmimport some-0.2.src.rpm
...
```

will import the given SRPMs to the branch ("srpms" by default) in the repository
(This operation is similar to `git-import-dsc` from `git-buildpackage`).

Importing SRPM creates a git layout similar to the "Like SRPM" scenario
described below.

## Tarballs

```sh
$ gear-update foo-0.2.tar.gz foo
$ gear-update foo-2.0.tar.gz foo
...
```

will update the subdirectory foo in the git repository with the contents of the
tarball. This operation is similar to `git-import-orig` from `git-buildpackage`.
As SRPMs may contain several sources, the source code is usually stored in a
subdirectory of the repository.

## Upstream VCS

This should be obvious: just fetch/pull if the upstream uses git, or use
conversion tools (e.g. `svn2git`, `cvs2git`) if it has not yet migrated to git.

# Packaging and patching

There are three major scenarios for keeping changes in the repository:
* Work with changes much like in SRPM era
* Keep patches in one branch
* Keep patches in specialized topic branches

## Scenario 1. "Like SRPM"

This simple scenario where git is used just for keeping history, and the usual
maintainer's workflow is not changed.

Branches in repository:
 master
 upstream

Tree layout:
```
 foo/                      (in upstream, master)
 .gear/rules               (in master)
 foo.spec                  (in master)
 foo-something-fixed.patch (in master)
 foo-another-fixed.patch   (in master)
```

git repository is generated by importing SRPMs or by creating from scratch.

### Importing tarball to the upstream branch

Use master branch to make it a bit easier

```sh
$ mkdir foo
$ cd foo
$ git init foo
$ gear-update ../foo-1.0.tar.gz foo
$ git branch upstream
```

### Add spec and patches

```sh
$ vi foo.spec
$ vi foo-something-fixed.patch
$ vi foo-another-fixed.patch
```

### Add gear/rules

The .gear/rules will have the following content:

```
copy: foo-something-fixed.patch
copy: foo-another-fixed.patch
tar.gz: foo
```

This sample rules file describes a source tarball from a `foo` directory and two patches.

Specfile is picked up automatically if there is only .spec in the root
directory fo git.

### Commiting the stuff

Gear is relying on the whole history being recorded by git. This means that any changes you'd like to see in RPM, must be committed to the repository.

```
$ git add .   # Commit the entire workdir
$ gear-commit # this is a wrapper around git-commit which uses the last
              # changelog entry as a commit message.
```

## Scenario 2. "Small fixes"

This scenario is useful for packages which deviate from upstream with a small number of non-overlapping
fixes here and there. This is also the easiest scenario to use.

Branches in repository:
 master
 upstream

Tree layout:
```
 foo/        (in upstream, patched in master)
 .gear/rules (in master)
 foo.spec    (in master)
```

### Working on package

```sh
$ git checkout master
$ vim ...     # hack-hack
$ git add ... # add new files if needed (optional)
$ git commit
```

All the changes are applied just on top of the upstream source code.

### .gear/rules

The .gear/rules file will be of the following form:

```
tar: v@version@:foo
diff: diff: v@version@:foo foo
```

This will generate foo.tar, containing upstream source code, taken from the tag
`v${version}`, where version is parsed from the `foo.spec`, and the diff is
containing the difference between the directory foo in `v${version}` tag and
current content of the directory foo.

Gear does not use real git tags, but instead it uses the tags stored in
`.gear/tags`. The reason for that is to keep packages reproduceable over time as
tags may move but SHA1 labels recorded at the time of run of `gear-update-tag`
will be able to address original changesets properly.

The `gear-update-tag` utility writes down SHA1 lables of all tags referenced in
package process to `.gear/tags`.

```sh
$ gear-update-tag --all
```

Don't forget to commit the changes after updating:

```sh
$ git-commit .gear/tags -m 'tags updated'
```

### Rebasing to a new upstream version

```sh
$ git merge upstream
# ... Fix conflicts, update changelog, remove unnecesary patches etc ...
$ gear-commit
```

That's all! As patches are stored in a git branch, it's easy to update to
a new upstream version: merge will detect most incosistences. As an
additional bonus, if the upstream uses git as well, patches forwarded
upstream and accepted there will not generate conflicts on merge.

### New package revision

```sh
$ vim ... # hack-hack, update changelog
$ gear-commit
```

Also simple.

## Scenario 3. "Full-blown development"

This is a scenario for the packages where downstream maintainers do a lot of
work (e.g. kernel) or they are upstream themselves. In this case each separate
feature is maintained in a separate branch and gear rules are used to
automatically produce patches for RPM.

Branches:
 upstream
 topic-A
 topic-B
 ...
 master

Tree layout:
```
 foo/        (in upstream, patched in topic-*, master)
 .gear/rules (in master)
 foo.spec    (in master)
```

### Working on package

All the work is done in topic branches, each is dedicated to some feature:

```sh
$ git checkout topic-A
$ vim ... # hack-hack-hack
$ git commit
$ git checkout topic-B
...
```

As patches may overlap, some conflict resolution needs to be
involved. The naive approach would be using the following branching
scheme:

```
 * upstream
 |
 \--> topic-A
 \--> topic-B
 \--> master
```

And then generating patch-per-topic by using .gear/rules. This will not always
work, as the generated patches might conflict.

To address the issue branching off each feature topic could be used:

```
 * upstream
 \-> topic-A
     \-> topic-B
         \-> master
```

And gear-merge(1) utility merges the branches as described in .gear/merge file:

```
merge: upstream topic-A
merge: topic-A topic-B
merge: topic-B master
```

After using this utility (and resolving all possible conflicts), master branch
gets a cumulative change.

### .gear/rules

The .gear/rules file will be exactly the same as for the previous scenario,
so the gear-update-tag(1) is also required:

```
tar: v@version@:foo
diff: diff: v@version@:foo foo
```

### Rebasing to a new upstream version

```sh
 $ ... # obtain the new upstream code in upstream branch
 $ gear-merge
 ... Fix conflicts, update changelog, remove unnecessary patches etc...
 $ gear-commit
```

Due to gear-merge, it's only necessary to fix the conflicts once.

### New package revision

```sh
$ vim ... # hack-hack, commit
$ gear-merge
```

# Builds

```sh
$ gear-hsh
```

`gear-hsh` first uses .gear/rules file to produce all needed parts of a SRPM.
After that gear will supply a created SRPM to a
[hasher](https://github.com/altlinux/hasher) build environment.

There are also other build commands: gear-rpm (uses `rpmbuild` instead of
[hasher](https://github.com/altlinux/hasher)) and
gear-remote-hsh/gear-remote-rpm, which use remote host for actual building
(communicating over SSH).

